#!/usr/bin/perl
#springer_concat  Copyright (C) 2008,2009  Tobias Domhan

#author: Tobias Domhan <tdomhan@gmail.com>
#license: GPL
#pdfs vom springer laden und zusammenfügen
#für windows habe ich die progress bar entfernt, da hierfür kein active perl package verfügbar ist


#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#You should have received a copy of the GNU General Public License
#along with this program.  If not, see <http://www.gnu.org/licenses/>



#benötigte module, müssen installiert sein!!

#BEGIN {
#	if($^O ne 'MSWin32') {
#		#unter Windows ist Term::ProgressBar nicht verfügbar
#		require Term::ProgressBar;
#	}
#}
use strict;
use URI::URL;
use LWP::UserAgent;
use HTTP::Request;
use HTTP::Request::Common;
use HTTP::Request::Form;
use HTML::TreeBuilder 3.0;
use PDF::Reuse;
use File::Copy;
use threads;
use Cwd;
use HTTP::Cookies;


my $proxy = $ENV{'http_proxy'};
my $destination = getcwd();
my $GUI=0;
my $running = 0;
#my $progress_bar;



#Crypt::SSLeay für https installieren
#ubuntu paket: libcrypt-ssleay-perl

if(scalar(@ARGV)<1) {
	#GUI
	$GUI = 1;
	require Tkx;
	
	my $url;#URL des Links 
	
	my $mw = Tkx::widget->new(".");
	$mw->g_wm_title("springer_concat (C) Tobias Domhan");
	$mw->g_wm_minsize(450, 155);

    my $go_button = $mw->new_button(
        -text => "Go",
        -command => sub {
			#start download in a new thread:
			Tkx::tk___messageBox(
					 -icon => "info",
					 -title => "gestartet",
					 -message => "Download im Hintergrund gestartet",
			);
			my $download_thread = threads->new(\&gui_start_download, $url);
		},
    );
	
	my $url_label = $mw->new_ttk__label(-text => "URL (z.B.: http://www.springerlink.com/content/j45844/)");
	$url_label->g_pack;
	
	my $url_input = $mw->new_ttk__entry(-textvariable => \$url, -width=> 70);
	$url_input->g_pack;
	
	my $destination_label = $mw->new_ttk__label(-text => "Ziel (z.B. C:\\Users\\Tobi\\ oder /home/tobi/)");
	$destination_label->g_pack;
	
	my $destination_input = $mw->new_ttk__entry(-textvariable => \$destination, -width=> 70);
	$destination_input ->g_pack;
	
	my $proxy_label = $mw->new_ttk__label(-text => "Proxy(optional):");
	$proxy_label->g_pack;
	
	my $proxy_input = $mw->new_ttk__entry(-textvariable => \$proxy, -width=> 70);
	$proxy_input ->g_pack;
	
	$go_button->g_pack;
	
    Tkx::MainLoop();
	
} else {
	#Kommandozeile
	$GUI=0;
	my $url;
	foreach $url(@ARGV) {
		get_pdfs($url);
	}
}


exit(0);

#Parameter: URL zum Springerdownload
sub gui_start_download {
	my $url = shift;	
	my $filename  = get_pdfs($url);
	my $running = 0;
}


###########################################################
# Define link extractors here: (refer to them inside "get_pdfs")
###########################################################

# An extractor returns an array. the last element will be the name of the book and the rest of the array will contain
# the filenames of the pdfs of which the ebook conists.

sub springerlinkextractor {
	my $tree = shift;
	my $url = shift;
	my $local_proxy = shift;
	
	my @files;
	#name des buches ermitteln
	my $name_element=$tree->look_down('class','MPReader_Profiles_SpringerLink_Content_PrimitiveHeadingControlName');
	my $buchname=$name_element->as_text;
	$buchname=~s/[^a-zA-z]//g;
	$buchname='outfile' if($buchname eq '');
	
	my %threads, my $i=0, my @files;
	my @elements = $tree->look_down('class', 'resourceLinks');
	#set_max_progress(scalar(@elements));
	foreach my $element (@elements) {
		#elemente durchgehen und herunterladen
		my $link_tag=$element->find_by_tag_name('a');
		my $link=$link_tag->attr('href');
		#wenn link angeben der die root url benötigt(d.h. fängt mit / an) entsprechend root url auslesen, sonst url und link normal verbinden
		if($link=~/content/) {
			$url=~/(.*\.com)/;
			my $base_url=$1;
			$link=$base_url.$link;
		} else {
			$link=$url.$link;
		}
		print "downloading $link ...\n";
		#start download 
		my $filename="${buchname}_${i}.pdf";
		download_file($link, $i, $filename, $local_proxy);
		push @files, $filename;
		$i++;
	}
	
	push @files, $buchname;
	return @files;
}

sub oldenlinkextractor {
	my $tree = shift;
	my $url = shift;
	my $local_proxy = shift;
	
	my @files;
	#name des buches ermitteln
	my $name_element=$tree->find_by_tag_name('title');	
	my $buchname=$name_element->as_text;
	$buchname=~m/.*\|(.*)/;
	$buchname=$1;
	$buchname=~s/[^a-zA-z]//g;
	$buchname='outfile' if($buchname eq '');	
	
	my %threads, my $i=0, my @files;
	my @elements = $tree->look_down('class', 'ref nowrap');
	#set_max_progress(scalar(@elements));
	foreach my $element (@elements) {
		#elemente durchgehen und herunterladen
		next if(not ($element->as_text =~ /PDF with links/));		
		my $link=$element->attr('href');
		next if(not ($link =~ /pdfplus/));
		#wenn link angeben der die root url benötigt(d.h. fängt mit / an) entsprechend root url auslesen, sonst url und link normal verbinden
		if($link=~/doi/) {
			$url=~/(.*\.com)/;
			my $base_url=$1;
			$link=$base_url.$link;
		} else {
			$link=$url.$link;
		}
		print "downloading $link ...\n";
		#start download 
		my $filename="${buchname}_${i}.pdf";
		download_file($link, $i, $filename, $local_proxy);
		push @files, $filename;
		$i++;
	}
	
	push @files, $buchname;
	return @files;
}


###########################################################
# End of link extractors
###########################################################

#lädt die pdf runter und schnürt diese zusammen
#Parameter: URL
#Rückgabe: Name der resultierenden PDF
sub get_pdfs {
	my %link_extractors = ("www.springerlink.com" => \&springerlinkextractor,"www.oldenbourg-link.com" => \&oldenlinkextractor);
	$running = 1;
	my $url=shift;
	my $local_proxy = $proxy;
	print "connecting to $url...";

	my $ua = LWP::UserAgent->new;
	$ua->cookie_jar({});
	
	$url=~m!http://(.*?)(/|$)!;
	my $domain=$1;
	
	if($domain eq "") {
		print "no vaild URL\n";
		return;
	}
	
	my $extractor = $link_extractors{$domain},"\n";
	if(not exists $link_extractors{$domain}) {
		print "no extractor available for $domain ... you may want to write your own and submit it to: http://code.google.com/p/springer-ebook-crawler/\n";
		return;
	}		
	my $req = HTTP::Request->new(GET => $url);
	$req->header(User_Agent   => 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.125 Safari/533.4');
	

	my $res = $ua->request($req);
	unless($res->is_success) {
		die "failed to connect to $url: ", $res->status_line, "\n";
	}
	print "connected\n";

	my $tree = HTML::TreeBuilder->new;
	$tree->parse($res->content);
	$tree->eof();
	
	my @files = $extractor->($tree, $url, $local_proxy);
	my $buchname = pop @files;

	#name des buches ermitteln
	# my $name_element=$tree->look_down('class','MPReader_Profiles_SpringerLink_Content_PrimitiveHeadingControlName');
	# my $buchname=$name_element->as_text;
	# $buchname=~s/[^a-zA-z]//g;
	# $buchname='outfile' if($buchname eq '');
	
	# my %threads, my $i=0, my @files;
	# my @elements = $tree->look_down('class', 'resourceLinks');
	# #set_max_progress(scalar(@elements));
	# foreach my $element (@elements) {
		# #elemente durchgehen und herunterladen
		# my $link_tag=$element->find_by_tag_name('a');
		# my $link=$link_tag->attr('href');
		# #wenn link angeben der die root url benötigt(d.h. fängt mit / an) entsprechend root url auslesen, sonst url und link normal verbinden
		# if($link=~/content/) {
			# $url=~/(.*\.com)/;
			# my $base_url=$1;
			# $link=$base_url.$link;
		# } else {
			# $link=$url.$link;
		# }
		# print "downloading $link ...\n";
		# #start download 
		# my $filename="${buchname}_${i}.pdf";
		# download_file($link, $i, $filename, $local_proxy);
		# push @files, $filename;
		# $i++;
	# }
	
	#pdfs zusammenfügen
	prFile($buchname.'.pdf');
	foreach(@files) {
		prDoc($_);
		unlink($_);
	}
	prEnd();
	if($destination) {
		#wenn ein Ziel angegeben wurde
		move($buchname.'.pdf', $destination);
	}
	print "\nfile saved as ${buchname}.pdf\n";
	$running = 0;
	return "${buchname}.pdf";
}

#Lädt ein PDF File von Springer runter
#1. Arg: Link
#2. Arg: Nummer
#3. Arg: Filename
#4. Arg: Proxy
sub download_file {
		my $link = shift;
		my $i = shift;
		my $filename=shift;
		my $proxy=shift;
		my $download_agent = LWP::UserAgent->new(agent => 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.125 Safari/533.4');
		$download_agent->cookie_jar( {} );
		#optional ein proxy:
		if($proxy) {
			$download_agent->proxy(['http', 'ftp'], $proxy);
		}		
		
		open(OUT, ">",$filename);
		binmode OUT;
		my $response;
		$response = $download_agent->get($link);
		unless($response->is_success) {
			#TODO bisher heruntergeladene Dateien löschen 
			die "failed to download $link: ", $response->status_line, "\n";
		}
		print OUT $response->content;
		close(OUT);
}

